package gsw.tool.pluggable.hook.hook;


import java.lang.reflect.Method;

import gsw.tool.pluggable.core.PluginManager;

/**
 * Hook工具类，统一进行Hook操作
 */
public class HookTool {

    /**
     * 添加Hook点：初始化Hook类
     *
     * @param baseHook    基础Hook类
     * @param classLoader 类加载器
     */
    public static void installHook(BaseHook baseHook, ClassLoader classLoader) {
        try {
            baseHook.onInit(classLoader);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加Hook点：给宿主Application调用
     */
    public final static void installHook() {
        installHook(new HookActivityManager(), PluginManager.getContext().getClassLoader());
        installHook(new HookPackageManager(), PluginManager.getContext().getClassLoader());
        installHook(new HookMH(), PluginManager.getContext().getClassLoader());
        installHook(new HookInstrumentation(), PluginManager.getContext().getClassLoader());
    }

    /**
     * 根据进程名判断，当时进程是否插件进程。
     * 注意：不能在Application.onCreate()中调用，因为ActivityThread还没生成，所以不能获得当前进程名。
     *
     * @return 是否插件进程：true代表是插件进程，false代表不是。
     */
    public static boolean isPluginService() {
        String processName = getProcessName();
        if (processName != null) {
            return processName.contains(":Plugin");
        }
        return false;
    }

    /**
     * 反射获取当前的进程名
     *
     * @return 当前的进程名
     */
    private static String getProcessName() {
        String processName = null;
        Class<?> ActivityThread = null;
        try {
            ActivityThread = Class.forName("android.app.ActivityThread");
            Method currentActivityThread = ActivityThread.getDeclaredMethod("currentActivityThread");
            currentActivityThread.setAccessible(true);
            Object am = currentActivityThread.invoke(null);
            Method getProcessName = ActivityThread.getDeclaredMethod("getProcessName");
            getProcessName.setAccessible(true);
            processName = (String) getProcessName.invoke(am);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
